﻿using System;
using System.Collections.Generic;
using Petra.Gis.ReferenceSystemServices;
using Petra.Gis.ReferenceSystemServices.Transformations;

namespace Petra.Gis.RenderingServices.PlanarBase 
{
  /// <summary>
  /// local cache for used transformations, that avoids lookup into main transform storage
  /// cache saves time necessary to search transform
  /// </summary>
  public class SRSTransformCache
  {

    protected MapBase _map;
    protected List<SRSTransform> _cache;


    protected SRSTransformCache()
    {
      _cache = new List<SRSTransform>();
    }





    public SRSTransformCache(MapBase map)
      :this()
    {
      _map = map;
    }




    public void Clear()
    {
      _cache = new List<SRSTransform>();
    }




    /// <summary>
    /// search for transform from supplied coordinate system
    /// into MapBase.ProjectedCoordinateSystem.
    /// Search starts in local cache,
    /// if no sutable transform found locally, creates new by searching complete transform db
    /// if forward only transform requested then forward only is stored to local cache
    /// if inverse requester both forward and reverse is stored ;-)
    /// </summary>
    /// <param name="dataSourceCS"></param>
    /// <returns>prepared coordinate transform, and this transform is also stored in cache</returns>
    public SRSTransform GetTransform(CoordinateSystem dataSourceCS, bool getInverseTransform)
    {

      // first look into local map cache for exactly same CS..
      // including inverse check
      foreach (SRSTransform t in _cache)
        if (t.Source.EqualParams(dataSourceCS, false) &&
            t.Target.EqualParams(_map.ProjectedCoordinateSystem, false)&&
            t.IsInverse == getInverseTransform)
          return t;

      // ok, not found ? create new transform
      // this call will throw error if no transform found
      SRSTransform tmp = SRSTransform.CreateFromCoordinateSystems(dataSourceCS, _map.ProjectedCoordinateSystem);
      _cache.Add(tmp);

      //if inverse is requested get also inverse version...
      if (getInverseTransform)
      {
        if (tmp.IsInversible)
          tmp = tmp.Inverse();
        else
          tmp = SRSTransform.CreateFromCoordinateSystems(_map.ProjectedCoordinateSystem, dataSourceCS);

        _cache.Add(tmp);
      }

      return tmp;

    }

  }
}
